/**
 * Created by ScorpionOrange on 2016/10/07.
 *
 * 给出两个整数a和b, 求他们的和, 但不能使用 + 等数学运算符。
 * a和b都是 32位 整数
 * 可以使用位运算符
 * 位运算符介绍：
 * 1、带符号左移( << )
 * 0000 0000 0000 0000 0000 0000 0000 0101 然后左移2位后，低位补0：//
 * 0000 0000 0000 0000 0000 0000 0001 0100 换算成10进制为20
 * System.out.println(5 << 2); // 运行结果是20
 *
 * 2、带符号右移( >> ) 高位补符号位
 * 0000 0000 0000 0000 0000 0000 0000 0101 然后右移2位，高位补0：
 * 0000 0000 0000 0000 0000 0000 0000 0001
 * System.out.println(5 >> 2);// 运行结果是1
 *
 * 3、无符号右移( >>> ) 高位补0
 * 例如 -5换算成二进制后为：0101 取反加1为1011
 * 1111 1111 1111 1111 1111 1111 1111 1011
 * 我们分别对5进行右移3位、 -5进行右移3位和无符号右移3位：
 * System.out.println(5 >> 3);// 结果是0
 * System.out.println(-5 >> 3);// 结果是-1
 * System.out.println(-5 >>> 3);// 结果是536870911
 *
 * 4、按位与( & )
 * 按位与：相同位的两个数字都为1，则为1；若有一个不为1，则为0。
 * 运算规则：0&0=0;    0&1=0;    1&0=0;    1&1=1;
 * System.out.println(5 & 3);// 结果为1
 * System.out.println(4 & 1);// 结果为0
 *
 * 5、按位或( | )
 * 按位或：相同位只要一个为1即为1。
 * 运算规则：0|0=0;    0|1=1;    1|0=1;    1|1=1;
 * System.out.println(5 | 3);// 结果为7
 *
 * 6、按位异或( ^ )
 * 按位异或：相同位不同则为1，相同则为0。
 * 运算规则：0^0=0;    0^1=1;    1^0=1;    1^1=0;
 * System.out.println(5 ^ 3);//结果为6
 *
 * 7、按位非 / 按位取反( ~ )
 * 按位取反：把0和1全部取反。
 * 运算规则：~1=0;    ~0=1;
 * System.out.println(~5);// 结果为-6
 *
 * 解题思路：
 * 考虑一个普通的加法计算：5＋17＝22
 *
 * 在十进制加法中可以分为如下3步进行：
 *    1. 忽略进位，只做对应各位数字相加，得到12（个位上5＋7＝12，忽略进位，结果2）；
 *    2. 记录进位，上一步计算中只有个位数字相加有进位1，进位值为10；
 *    3. 按照第1步中的方法将进位值与第1步结果相加，得到最终结果22。
 *
 * 下面考虑二进制数的情况（5＝101，17＝10001）：
 * 仍然分3步：
 *    1. 忽略进位，对应各位数字相加，得到10100；
 *    2. 记录进位，本例中只有最后一位相加时产生进位1，进位值为10（二进制）；
 *    3. 按照第1步中的方法将进位值与第1步结果相加，得到最终结果10110，正好是十进制数22的二进制表示。
 *
 * 接下来把上述二进制加法3步计算法用位运算替换：
 *    第1步（忽略进位）：0＋0＝0，0＋1＝1，1＋0＝0，1＋1＝0，典型的异或运算。
 *    第2步：很明显，只有1＋1会向前产生进位1，相对于这一数位的进位值为10，而10＝(1&1)<<1。
 *    第3步：将第1步和第2步得到的结果相加，其实又是在重复这2步，直到不再产生进位为止。
 */
public class Solution {
    /*
     * param a: The first integer
     * param b: The second integer
     * return: The sum of a and b
     */
    public int aplusb(int a, int b) {
        // write your code here, try to do it without arithmetic operators.
        if(a == 0) {
            return b;
        }
        else if(b == 0){
            return a;
        }
        else {
            int x1 = a^b;
            int x2 = (a & b) << 1;
            return aplusb(x1, x2);
        }
    }
}
